#include "middleware.h"
#include "..\pcommon\pcommon.h"
#include "..\gvs\gvs.h"
#include "..\GUISys\GUISys.h"
#include "..\pcommon\zone.h"


#define MAXPRINTMSG 4096

// Structure containing functions exported from refresh DLL
gvsexport_t	ge;
guiexport_t gui_exp;

static HINSTANCE	gvslib_library;		/* Handle to refresh DLL */
static pboolean		gvslib_active = false;

static HINSTANCE	guilib_library;		/* Handle to gui DLL */
static pboolean		guilib_active = false;

/* for gvs */
extern void PreInit(void);
extern void WaitForInit(void);

/* for gui system */
extern IDirectDrawSurface7* DDLoadBitmap(IDirectDraw7*, LPCSTR, int, int);
extern HRESULT DDReLoadBitmap(IDirectDrawSurface7*, LPCSTR);

extern pboolean g_cmd_with_gui;

void Refresh_FreeLib(void)
{
	if ( 0 == FreeLibrary( gvslib_library ) )
	{
		Com_Error("GVS FreeLibrary failed");
	}
	memset (&ge, 0, sizeof(ge));
	gvslib_library = NULL;
	gvslib_active  = false;
}

void GetConfig(shooter_ptr pShooter)
{
	if (g_cmd_with_gui)
		gui_exp.Get_Config(pShooter);
	else
		memset(pShooter, 0, sizeof(pShooter));
}

pboolean Refresh_LoadLib(char* name)
{
	gvsimport_t	gi;
	GetGVSAPI_t	GetGVSAPI;
	
	if (true == gvslib_active)
	{
		ge.Shutdown();
		Refresh_FreeLib();
	}

	if (0 == (gvslib_library = LoadLibrary(name)))
	{
		Com_Error("Library %s is not found.", name);
	}
	
	/* init import library */
	gi.Sys_Error= Com_Error;
	gi.Sys_Printf = Com_Printf;
	gi.Pre_Init	= PreInit;
	gi.Wait_For_Init = WaitForInit;
	gi.Get_Zone	= Get_Global_Zone;
	gi.zf		= Z_Free;
	gi.zm		= Z_Malloc;
	gi.zs		= Z_Stats_f;
	gi.Get_Config= GetConfig;
	
	if (0 == (GetGVSAPI = (void *)GetProcAddress(gvslib_library, "GetGVSAPI")))
	{
		Refresh_FreeLib();
		Com_Error("GetProcAddress failed on %s", name);
	}

	ge = GetGVSAPI(gi);

	if (API_VERSION != ge.api_version)
	{
		Refresh_FreeLib();
		Com_Error("%s has incompatible api_version", name);
	}

	gvslib_active = true;

	return true;
}

void GUI_FreeLib(void)
{
	if ( 0 == FreeLibrary( guilib_library ) )
	{
		Com_Error("GUI FreeLibrary failed");
	}
	memset (&gui_exp, 0, sizeof(gui_exp));
	guilib_library = NULL;
	guilib_active  = false;
}

pboolean GUI_LoadLib(char* name)
{
	guiimport_t gui_imp;
	GetGUIAPI_t GetGUIAPI;

	if (true == guilib_active)
	{
		GUI_FreeLib();
	}

	if (0 == (guilib_library = LoadLibrary(name)))
	{
		Com_Error("Library %s is not found.", name);
	}

	/* init import library */
	gui_imp.global_hInstance = global_hInstance;
	gui_imp.Sys_Error	= Com_Error;
	gui_imp.Sys_Printf	= Com_Printf;
	gui_imp.Get_Zone	= Get_Global_Zone;
	gui_imp.zf			= Z_Free;
	gui_imp.zm			= Z_Malloc;
	gui_imp.zs			= Z_Stats_f;
	gui_imp.Load_Bitmap	= DDLoadBitmap;
	gui_imp.ReLoad_Bitmap=DDReLoadBitmap;

	if (0 == (GetGUIAPI = (void *)GetProcAddress(guilib_library, "GetGUIAPI")))
	{
		GUI_FreeLib();
		Com_Error("GetProcAddress failed on %s", name);
	}

	gui_exp = GetGUIAPI(gui_imp);

	if (API_VERSION != gui_exp.api_version)
	{
		GUI_FreeLib();
		Com_Error("%s has incompatible api_version", name);
	}

	guilib_active = true;

	return true;
}

void Mid_LoadLib(void)
{
	/* Load refresh library */
	if (false == Refresh_LoadLib("gvs.dll"))
	{
		Refresh_FreeLib();
		Com_Error("Can't load refresh library.");
	}

	if (g_cmd_with_gui)
	{
		/* Load gui library */
		if (false == GUI_LoadLib("GUISys.dll"))
		{
			GUI_FreeLib();
			Com_Error("Can't load gui library.");
		}
	}
}

void Mid_FreeLib(void)
{
	Refresh_FreeLib();
	if (g_cmd_with_gui)
	{
		/* uninit global configuration data */
		gui_exp.Drop_Shooter_Ptr();
		GUI_FreeLib();
	}
}

pboolean Vid_Init(void)
{
	return ge.Init(global_hInstance, ge.WndProc);
}

void Vid_Update()
{
	ge.RenderFrame();
}

void Vid_Shutdown()
{
	ge.Shutdown();
}

/*
=================
GUI_Init
=================
*/
pboolean GUI_Init(void)
{
	return gui_exp.Pre_GUI_Init();
}

